/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * File Name          : freertos.c
 * Description        : Code for freertos applications
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2025 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "../../User/button/button.h"
#include "../../User/my_define.h"
#include "../../User/oled/bsp_oled_debug.h"
#include "../../User/tca9548a/tca9548a.h"
#include "../../User/tlv493d/tlv493d.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
osThreadId defaultTaskHandle;
osThreadId myTask02Handle;
uint32_t myTask02Buffer[ 128 ];
osStaticThreadDef_t myTask02ControlBlock;
osThreadId myTask03Handle;
uint32_t myTask03Buffer[ 128 ];
osStaticThreadDef_t myTask03ControlBlock;
osThreadId myTask04Handle;
uint32_t myTask04Buffer[ 128 ];
osStaticThreadDef_t myTask04ControlBlock;
osThreadId myTask05Handle;
uint32_t myTask05Buffer[ 128 ];
osStaticThreadDef_t myTask05ControlBlock;

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void const * argument);
void sensor_f(void const * argument);
void contral_f(void const * argument);
void oled_f(void const * argument);
void button_f(void const * argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );

/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t  xIdleStack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory(StaticTask_t** ppxIdleTaskTCBBuffer, StackType_t** ppxIdleTaskStackBuffer, uint32_t* pulIdleTaskStackSize)
{
    *ppxIdleTaskTCBBuffer   = &xIdleTaskTCBBuffer;
    *ppxIdleTaskStackBuffer = &xIdleStack[0];
    *pulIdleTaskStackSize   = configMINIMAL_STACK_SIZE;
    /* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
    /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
    /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
    /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
    /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* definition and creation of myTask02 */
  osThreadStaticDef(myTask02, sensor_f, osPriorityNormal, 0, 128, myTask02Buffer, &myTask02ControlBlock);
  myTask02Handle = osThreadCreate(osThread(myTask02), NULL);

  /* definition and creation of myTask03 */
  osThreadStaticDef(myTask03, contral_f, osPriorityNormal, 0, 128, myTask03Buffer, &myTask03ControlBlock);
  myTask03Handle = osThreadCreate(osThread(myTask03), NULL);

  /* definition and creation of myTask04 */
  osThreadStaticDef(myTask04, oled_f, osPriorityNormal, 0, 128, myTask04Buffer, &myTask04ControlBlock);
  myTask04Handle = osThreadCreate(osThread(myTask04), NULL);

  /* definition and creation of myTask05 */
  osThreadStaticDef(myTask05, button_f, osPriorityRealtime, 0, 128, myTask05Buffer, &myTask05ControlBlock);
  myTask05Handle = osThreadCreate(osThread(myTask05), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
    /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
 * @brief  Function implementing the defaultTask thread.
 * @param  argument: Not used
 * @retval None
 */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN StartDefaultTask */
    /* Infinite loop */
    for (;;)
    {
        osDelay(1);
    }
  /* USER CODE END StartDefaultTask */
}

/* USER CODE BEGIN Header_sensor_f */
/**
 * @brief Function implementing the myTask02 thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_sensor_f */
void sensor_f(void const * argument)
{
  /* USER CODE BEGIN sensor_f */
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
    TCA_Init(&machine.tca_i2c, &machine.dev_i2c, TCA9548A_DEFAULT_ADDR);
    TCA_SelectChannel(&machine.tca_i2c, TCA_CHANNEL_1);
    Tlv493d_Reset(&machine.sensor1, TLV493D_ADDR1);
    Tlv493d_Setup(&machine.sensor1);
    Tlv493d_SetConversionMode(&machine.sensor1, CONVMODE_12_BIT);
    TCA_SelectChannel(&machine.tca_i2c, TCA_CHANNEL_2);
    Tlv493d_Reset(&machine.sensor2, TLV493D_ADDR1);
    Tlv493d_Setup(&machine.sensor2);
    Tlv493d_SetConversionMode(&machine.sensor2, CONVMODE_12_BIT);
    TCA_SelectChannel(&machine.tca_i2c, TCA_CHANNEL_3);
    Tlv493d_Reset(&machine.sensor3, TLV493D_ADDR1);
    Tlv493d_Setup(&machine.sensor3);
    Tlv493d_SetConversionMode(&machine.sensor3, CONVMODE_12_BIT);
    //	TCA_SetMultipleChannels(NULL, uint8_t _state_data)
    //      TCA9548A_SelectChannel(TCA9548A_DEFAULT_ADDR, TCA_CHANNEL_1);
    //      TLV493D_Init(TLV493D_MODE_LOW_POWER);
    //      TCA9548A_SelectChannel(TCA9548A_DEFAULT_ADDR, TCA_CHANNEL_2);
    //      TLV493D_Init(TLV493D_MODE_LOW_POWER);
    //      TCA9548A_SelectChannel(TCA9548A_DEFAULT_ADDR, TCA_CHANNEL_3);
    //      TLV493D_Init(TLV493D_MODE_LOW_POWER);
    /* Infinite loop */
    for (;;)
    {
        TCA_SelectChannel(&machine.tca_i2c, TCA_CHANNEL_1);
        Tlv493d_UpdateData(&machine.sensor1);
        TCA_SelectChannel(&machine.tca_i2c, TCA_CHANNEL_2);
        Tlv493d_UpdateData(&machine.sensor2);
        TCA_SelectChannel(&machine.tca_i2c, TCA_CHANNEL_3);
        Tlv493d_UpdateData(&machine.sensor3);

        //      TCA9548A_SelectChannel(TCA9548A_DEFAULT_ADDR, TCA_CHANNEL_1);
        //      TLV493D_ReadData(&machine.sensor1);
        //      TCA9548A_SelectChannel(TCA9548A_DEFAULT_ADDR, TCA_CHANNEL_2);
        //      TLV493D_ReadData(&machine.sensor2);
        //      TCA9548A_SelectChannel(TCA9548A_DEFAULT_ADDR, TCA_CHANNEL_3);
        //      TLV493D_ReadData(&machine.sensor3);
        // if(machine.state == STATE_REST)
        // {
        //     machine.sensor1.mag_x = 0;
        //     machine.sensor1.mag_y = 0;
        //     machine.sensor1.mag_z = 0;
        //     machine.sensor2.mag_x = 0;
        //     machine.sensor2.mag_y = 0;
        //     machine.sensor2.mag_z = 0;
        //     machine.sensor3.mag_x = 0;
        //     machine.sensor3.mag_y = 0;
        //     machine.sensor3.mag_z = 0;
        // }
        // else
        // {
        //   machine.sensor1.mag_x = 120;
        //   machine.sensor1.mag_y = 110;
        //   machine.sensor1.mag_z = 101;
        //   machine.sensor2.mag_x = 110;
        //   machine.sensor2.mag_y = 100;
        //   machine.sensor2.mag_z = 99;
        //   machine.sensor3.mag_x = 0;
        //   machine.sensor3.mag_y = 2;
        //   machine.sensor3.mag_z = 1;
        // }
        osDelay(10);
    }
  /* USER CODE END sensor_f */
}

/* USER CODE BEGIN Header_contral_f */
/**
 * @brief Function implementing the myTask03 thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_contral_f */
void contral_f(void const * argument)
{
  /* USER CODE BEGIN contral_f */
    /* Infinite loop */
    for (;;)
    {
        if (machine.sensor1.dataVal.x > 100)
        {
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
            machine.sensor1_sate = 1;
        }
        else
        {
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
            machine.sensor1_sate = 0;
        }
        if (machine.sensor2.dataVal.x > 100)
        {
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
            machine.sensor2_sate = 1;
        }
        else
        {
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
            machine.sensor2_sate = 0;
        }
        if (machine.sensor3.dataVal.x > 100)

        {
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
            machine.sensor3_sate = 1;
        }
        else
        {
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
            machine.sensor3_sate = 0;
        }
        if(machine.sensor1_sate == 1 || machine.sensor2_sate == 1 || machine.sensor3_sate == 1)
        {
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
        }
        else
        {
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
        }
        osDelay(10);
    }
  /* USER CODE END contral_f */
}

/* USER CODE BEGIN Header_oled_f */
/**
 * @brief Function implementing the myTask04 thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_oled_f */
void oled_f(void const * argument)
{
  /* USER CODE BEGIN oled_f */
    OLED_Init();
    OLED_Fill(0x00);
    /* Infinite loop */
    for (;;)
    {
        if (machine.state == STATE_RUNNING)
        {
          sprintf(machine.oled_1row, "RUNNING...");
					sprintf(machine.oled_2row, "x:%05d  y:%05d", machine.sensor1.dataVal.x, machine.sensor1.dataVal.y);
					sprintf(machine.oled_3row, "z:%04d", machine.sensor1.dataVal.z);
					if (machine.sensor1_sate == 1)
					{
							sprintf(machine.oled_3row + strlen(machine.oled_3row), "  correct");
					}
					else
					{
							sprintf(machine.oled_3row + strlen(machine.oled_3row), "  error ");
					}
					sprintf(machine.oled_4row, "x:%05d  y:%05d", machine.sensor2.dataVal.x, machine.sensor2.dataVal.y);
					sprintf(machine.oled_5row, "z:%05d", machine.sensor2.dataVal.z);
					if (machine.sensor2_sate == 1)
					{
							sprintf(machine.oled_5row + strlen(machine.oled_5row), "  correct");
					}
					else
					{
							sprintf(machine.oled_5row + strlen(machine.oled_5row), "  error  ");
					}
					sprintf(machine.oled_6row, "x:%05d  y:%05d", machine.sensor3.dataVal.x, machine.sensor3.dataVal.y);
					sprintf(machine.oled_7row, "z:%05d", machine.sensor3.dataVal.z);
					if (machine.sensor3_sate == 1)
					{
							sprintf(machine.oled_7row+ strlen(machine.oled_7row), "  correct");
					}
					else
					{
							sprintf(machine.oled_7row+ strlen(machine.oled_7row), "  error  ");
					}
					OLED_ShowStr(0, 0, (unsigned char*)machine.oled_1row, 1);
					OLED_ShowStr(0, 2, (unsigned char*)machine.oled_2row, 1);
					OLED_ShowStr(0, 3, (unsigned char*)machine.oled_3row, 1);
					OLED_ShowStr(0, 4, (unsigned char*)machine.oled_4row, 1);
					OLED_ShowStr(0, 5, (unsigned char*)machine.oled_5row, 1);
					OLED_ShowStr(0, 6, (unsigned char*)machine.oled_6row, 1);
					OLED_ShowStr(0, 7, (unsigned char*)machine.oled_7row, 1);
        }
        else
        {
						OLED_Fill(0x00);
            sprintf(machine.oled_1row, "RESET...");
        }
        osDelay(1);
    }
  /* USER CODE END oled_f */
}

/* USER CODE BEGIN Header_button_f */
/**
 * @brief Function implementing the myTask05 thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_button_f */
void button_f(void const * argument)
{
  /* USER CODE BEGIN button_f */
    button_setup();
    /* Infinite loop */
    for (;;)
    {
        button_loop();
        osDelay(pdMS_TO_TICKS(20));
    }
  /* USER CODE END button_f */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

